﻿// ## 2023/09/03 # 铃 # 重构 ##

namespace AI_ATTACK_CITY_WEIGHT
{
    const int 每级难度影响玩家受攻击权重 = 20;



    class Main
    {

        pk::c_bool 调试模式 = pk::c_bool(false);

        Main()
        {

            pk::set_func(263, pk::func263_t(callback));
            pk::set_func(264, pk::func264_t(callback2));
            pk::bind(260, pk::trigger260_t(AI进攻选择_263_打印));
        }

        void AI进攻选择_263_打印()
        {
            ImGui::Checkbox("调试模式", 调试模式);
        }

        pk::building @final_base;
        int 铃据点1 = 铃据点_汉中;
        int 铃据点2 = 铃据点_巴东;
        int 铃据点3 = 铃据点_南海;

        pk::building @callback2(pk::ai_context @context, pk::building @building)
        {
            return calc_weight(building);
        }
        pk::building @calc_weight(pk::building @building)
        {
            //pk::trace(pk::format("func_263,{},打印开关{}", pk::decode(pk::get_name(building)),调试模式.v));
            if (building.is_player())
                return pk::get_district_best_target(building);

            pk::district @district = pk::get_district(building.get_district_id());

            if (building.is_player())
            {
                if (district.policy == 3 and building.troops > 30000 and pk::get_food(building) > 50000)
                    return pk::get_building(district.policy_target);

                // pk::trace(pk::format("走新的函数{}", pk::get_new_base_name(building.get_id())));
                // return pk::get_district_best_target(building);

            }

            int src_id = building.get_id();
            int src_force_id = building.get_force_id();
            pk::force @src_force = pk::get_force(src_force_id);
            int src_city_id = pk::get_city_id(building.pos);
            pk::person@kunshu = pk::get_person(src_force.kunshu);

            if (pk::get_idle_person_list(building).count < 5)
                return null;



                //pk::trace("func_264 pos0");
                // ********************************* 初始化- 获取周边据点列表 *******************************************
            pk::list<pk::building @> building_list = ai::base_near_baselist[src_id];

            if (building_list.count <= 0)
                return null;

            // ********************************* 初始化-把正在攻击的据点放入列表******************************************
            pk::list<pk::force @> attacking_force;
            pk::list<pk::building @> attacking_building;
            pk::array<int> attacking_building_troops(据点_末, 0);
            pk::array<int> attacking_force_troops(势力_末, 0);

            for (int i = 0; i < 据点_末; i++)
            {
                attacking_building_troops[i] = 0;
            }

            for (int i = 0; i < 势力_末; i++)
            {
                attacking_force_troops[i] = 0;
            }


            for (int i = 0; i < 据点_末; i++)
            {
                pk::building @dst_building = pk::get_building(i);
                if (ai::force_attack_base_troops[src_force_id][i] > 10000)
                {
                    attacking_building.add(pk::get_building(i));

                    pk::force @dst_force = pk::get_force(dst_building.get_force_id());
                    if (dst_force !is null)
                    {
                        attacking_force_troops[dst_building.get_force_id()] += ai::force_attack_base_troops[src_force_id][i];
                        if (attacking_force_troops[dst_building.get_force_id()] > 10000 and !attacking_force.contains(dst_force))
                            attacking_force.add(dst_force);
                    }
                }
            }

            // ********************************* 初始化-攻击方战力计算*****************************************
            int 己方进攻战斗力 = ai::base_atk_power[src_id];
            int 可出征兵力 = pk::get_troops(building) - ai::retained_troops[building.get_id()];

            if (调试模式.v)
                pk::trace(" 己方战力因子:目的地:" + pk::decode(pk::get_name(building)) + "  可出征兵力:" + 可出征兵力 + "  留存兵力:" + ai::retained_troops[building.get_id()]);

            if (调试模式.v)
                pk::trace(" 己方战力因子:出发地:" + pk::decode(pk::get_name(building)) + "  己方进攻战斗力:" + 己方进攻战斗力 + "  己方防御战斗力" + ai::base_def_power[src_id] + "  marchable_troops" + ai::marchable_troops[building.get_id()]);


             // ********************************* 初始化-受到攻击时不出征****************************************
            if (ai::base_attacked_troops[building.get_id()] > 5000)
            {
                if (调试模式.v)
                    pk::trace(" 受到攻击不出征:" + pk::decode(pk::get_name(building)) + "  enemy_target" + ai::base_attacked_troops[building.get_id()]);
                return null;
            }

            // ********************************* 初始化-己方相邻据点受到攻击不出征****************************************
            auto src_near_building_list = ai::base_near_baselist[src_id];
            for (int j = 0; j < src_near_building_list.count; j++)
            {
                int src_neighbor_base_id = src_near_building_list[j].get_id();

                // 临近的己方据点正在被攻击,且除以劣势
                if (ai::base_attacked_troops[src_neighbor_base_id] - pk::get_troops(src_near_building_list[j]) > 10000 and src_near_building_list[j].get_force_id() == src_force_id)
                {
                    if (调试模式.v)
                        pk::trace(" 己方相邻据点受到攻击不出征:" + pk::decode(pk::get_name(building)) + "  enemy_target" + ai::base_attacked_troops[src_neighbor_base_id]);
                    return null;
                }
            }

            // *************************************************** 权重计算开始************************************************************
            array<int32> weight(据点_末, 0);
            int max_weight_building_id = -1;
            int max_weight = -1;

            for (int i = 0; i < building_list.count; ++i)
            {
                pk::building @dst_base = building_list[i];
                int dst_id = dst_base.get_id();
                if (!pk::is_alive(dst_base))
                    continue;

                int dst_force_id = dst_base.get_force_id();
                pk::force @dst_force = pk::get_force(dst_force_id);

                      // *********************************排除错误据点*****************************************
                if (dst_id == src_id)
                    continue;

                if (dst_force_id == src_force_id)
                    continue;

                if (调试模式.v)
                    pk::trace(" 排除非敌对的:出发地:" + pk::decode(pk::get_name(building)) + " 目的地:" + pk::decode(pk::get_name(dst_base)) + "  己方进攻战斗力:" + 己方进攻战斗力 + "  己方防御战斗力" + ai::base_def_power[src_id] + "  marchable_troops" + ai::marchable_troops[building.get_id()]);


                if (!pk::is_enemy(dst_force_id, src_force_id) and dst_force_id != -1)
                    continue;

                //    pk::trace(" 停战时间判断:目的地:" + pk::decode(pk::get_name(building)) + "到" + pk::decode(pk::get_name(dst_base)) + "停战时间为" + src_force.ceasefire_timer[dst_force_id] );
                //    if(src_force.ceasefire_timer[dst_force_id] !=0)
                //     continue;

                if (调试模式.v)
                    pk::trace(" 权重计算开始:出发地:" + pk::decode(pk::get_name(building)) + " 目的地:" + pk::decode(pk::get_name(dst_base)) + "  己方进攻战斗力:" + 己方进攻战斗力 + "  己方防御战斗力" + ai::base_def_power[src_id] + "  marchable_troops" + ai::marchable_troops[building.get_id()]);

                 // ********************************* 己方支援战斗力****************************************
                pk::list<pk::building @> dst_near_building_list = ai::base_near_baselist[dst_id];
                int 己方支援战斗力 = 0;
                for (int j = 0; j < dst_near_building_list.count; j++)
                {
                    int dst_neighbor_base_id = dst_near_building_list[j].get_id();

                    // 临近的己方据点不在正在被攻击,可作为潜在支援战斗力
                    if (ai::base_attacked_troops[dst_neighbor_base_id] == 0 and dst_near_building_list[j].get_force_id() == src_force_id)
                    {
                        //  if (dst_id == 铃据点_宛)
                        // pk::trace(" 己方支援据点:" + pk::decode(pk::get_name(dst_near_building_list[j])) );

                        己方支援战斗力 += ai::base_atk_power[dst_neighbor_base_id] / 2;
                    }
                }

                      // ********************************* 据点相关:据点战斗力因子*****************************************
                int 目标总防御能力;
                int 目标野战战斗力 = ai::base_atk_power[dst_id];
                int 目标守城战斗力 = ai::base_def_power[dst_id] + ch::base_enemy_not_from_force(dst_base, src_force);
                int 目标大城野战战斗力 = 0;
                int 支援部队战斗力 = 0;

            // 小城市和关卡还要考虑所在的同势力的大城战斗力
                if (dst_base.get_force_id() == pk::get_city(pk::get_city_id(dst_base.pos)).get_force_id() and dst_base.facility != 设施_都市)
                {
                    pk::building @dst_base_city = pk::get_building(pk::get_city(pk::get_city_id(dst_base.pos)).get_id());
                    目标大城野战战斗力 = ai::base_atk_power[dst_base_city.get_id()];;

                }

                auto dst_force_near_building_list = ai::base_near_baselist[dst_id];
                for (int j = 0; j < dst_force_near_building_list.count; j++)
                {
                    int neighbor_force_base_id = dst_force_near_building_list[j].get_id();
                    if (neighbor_force_base_id == -1 or neighbor_force_base_id >= 据点_末)
                        continue;

                    if (dst_force_near_building_list[j].get_force_id() != dst_base.get_force_id())
                        continue;

                    if (pk::get_building_distance(neighbor_force_base_id, dst_id, dst_force_near_building_list[j].get_force_id()) > 1)
                        continue;
                    支援部队战斗力 += ai::base_atk_power[neighbor_force_base_id];

                }
                目标总防御能力 = 目标野战战斗力 + 目标守城战斗力 + 支援部队战斗力;

                if (调试模式.v)
                    pk::trace(" 目标战力因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  目标总防御能力:" + 目标总防御能力 + "  目标野战战斗力:" + 目标野战战斗力 + "  目标守城战斗力:" + 目标守城战斗力 + "  支援部队战斗力:" + 支援部队战斗力);


                // ********************************* 初始化-263.相关计算 *******************************************
                int 舰船数量 = pk::get_weapon_amount(building, 兵器_斗舰) + pk::get_weapon_amount(building, 兵器_楼船);

                // 恶劣地形需要增加出兵数
                int m = 0;
                int path = pk::get_route(building.get_id(), dst_base.get_id(), building.get_force_id(), true);
                if (path == 路径_栈道)
                    continue;
                if (path == 路径_海洋)
                    m = pk::max(50 - 舰船数量 * 3, 20);
                else if (path == 路径_栈道)
                {
                    if (building.has_tech(技巧_难所行军))
                        m = 30;
                    else
                        m = 50;
                }

                // *********************************** 势力排名初始化,势力对出兵的影响*****************************************
                int src_rank = ai::force_list.index_of(pk::get_force(src_force_id));
                int dst_rank = ai::force_list.index_of(pk::get_force(dst_force_id));
                int force_count = ai::force_list.count;
                int rank_diff = dst_rank - src_rank;  //进攻方领先多少排名.
                int k = 0;
                int g = 0;
                if (force_count > 6)
                {
                    k = int((0.0 - float(rank_diff) / force_count) * 30); // 领先对方越多,,越是可以降低自己的出征要求,最强势力对最弱降低25%,
                    g = int((0.5 - float(dst_rank) / force_count) * 20);    // 目标势力越弱,越是可以降低自己的出征要求,越强越增加,对最强势力提高10%,对最弱势力减少10%
                }

                int required = pk::max(80, pk::min(200, (100 + m + k + g)));

                // *********************************** 战斗力不足不进攻*****************************************

                if (attacking_building.contains(dst_base) and attacking_building_troops[dst_id] > 20000)
                    required /= 2;

                if (调试模式.v)
                    pk::trace(" 出征判决因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  己方进攻战斗力:" + 己方进攻战斗力 + "  己方支援战斗力:" + 己方支援战斗力 + " 总势力数:" + force_count + " 势力排名之差:" + rank_diff + " 己方势力排名:" + src_rank + "  目标势力排名:" + dst_rank + "  k:" + k + "  g:" + g + "  要求系数:" + required + "  要求战力:" + 目标总防御能力 * required / 100);



                // 仅有玩家相邻,且目标就是玩家,则疯狗进攻
                if (ch::get_neighbor_player_base(building) == 1 and dst_base.is_player())
                    可出征兵力 = pk::get_troops(building) - int(ai::retained_troops[building.get_id()] * 0.8);

                // 和玩家相邻不止一个,但是进攻的为玩家据点,也要偏保守一些
                else if (ch::get_neighbor_player_base(building) > 1 and dst_base.is_player())
                    可出征兵力 = 可出征兵力 - (ch::get_neighbor_player_base(building) - 1) * 10000;

                // 和玩家相邻不止一个,而且进攻的不为玩家据点,则非常保守
                else if (ch::get_neighbor_player_base(building) > 1 and !dst_base.is_player())
                    可出征兵力 = 可出征兵力 - ch::get_neighbor_player_base(building) * 10000 + 10000;

                if (调试模式.v)
                    pk::trace(" 出征判决因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  可出征兵力:" + 可出征兵力 + "  目标兵力*0.8:" + pk::get_troops(dst_base) * 0.8);

                if (可出征兵力 < 25000)
                    continue;


                // 兵力小于8万才有这些判定条件.
                if (pk::get_troops(building) < 80000)
                {

                    if (可出征兵力 < int(pk::get_max_marchable_troops(dst_base) * 0.8))
                        continue;

                    if (己方进攻战斗力 < 目标总防御能力 * 80 / 100 * required / 100 and 可出征兵力 < int(pk::get_troops(dst_base)))
                        continue;

                    if ((己方进攻战斗力 + 己方支援战斗力) < 目标总防御能力 * required / 100 * 120 / 100 and pk::get_troops(building) < pk::get_max_troops(building))
                        continue;

                    if (dst_base.troops == 0 and dst_force_id == -1)
                    {
                        if (pk::get_troops(building) < 30000 or pk::get_food(building) < 60000)
                            continue;
                    }
                    else
                    {
                        if (pk::get_troops(building) < 50000)
                            continue;
                    }
                }
                // ***********************************玩家军团设置*****************************************

            //为了避免反复进出BUG,符合前置条件之后,玩家军团直接返回目标值

                if (building.is_player() and district.no > 1 and district.policy == 3)
                {
                    pk::trace(pk::format("{},军团no,{}军团政策:{},政策对象:{},当前目标城市:{},", pk::decode(pk::get_name(building)), district.no, district.policy, district.policy_target, pk::decode(pk::get_name(dst_base))));

                    if (dst_base.get_id() == district.policy_target)
                        return dst_base;
                    else continue;
                }


                if (building.is_player() and district.no > 1)
                {
                    if (district.policy == 0 and dst_base.get_force_id() == district.policy_target)
                        weight[dst_id] += 100;

                    else if (district.policy == 3 and dst_base.get_id() == district.policy_target)
                        weight[dst_id] += 100;
                }
                // pk::trace(pk::format("{},军团no,{}军团政策:{},政策对象:{},中期目标:{},中期目标对象:{}", pk::decode(pk::get_name(building)), district.no, district.policy, district.policy_target, district.mid_objective, district.mid_objective_target));

                if (调试模式.v)
                {
                    pk::trace(pk::format("{},军团no,{}军团政策:{},政策对象:{},中期目标:{},中期目标对象:{}", pk::decode(pk::get_name(building)), district.no, district.policy, district.policy_target, district.mid_objective, district.mid_objective_target));

                    pk::trace(" 军团影响因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + " 军团NO:" + district.no + " 军团政策:" + district.policy + " 军团对象:" + district.policy_target);
                }


                // ********************************* 战力相关 : 根据战力设置初始值******************************************

              // ********************************* 空城加权因子*****************************************


                if ((dst_force_id < 0 || dst_force_id >= 势力_末))
                {
#if param_set
                    if (dst_base.facility == 设施_城市)
                        weight[dst_id] += pk::get_attack_param().empty_city_weight;
                    else
                        weight[dst_id] += pk::get_attack_param().empty_gate_weight;
#endif
#if not_param_set
                    if (dst_base.facility == 设施_城市)
                        weight[dst_id] += int(pk::core["ai.attack.weight.empty_city_weight"]);
                    else
                        weight[dst_id] += int(pk::core["ai.attack.weight.empty_gate_weight"]);
#endif

                    if (调试模式.v)
                        pk::trace(" 空城加权因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id]);
                }

                //空城不能被反复计算.
                else
                {
                    weight[dst_id] += 50 - pk::min(目标总防御能力 / 5, 100);

                    if (调试模式.v)
                        pk::trace(" 目标战力因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  目标总防御能力:" + 目标总防御能力);
                }

                // ********************************* 地理.路径相关 : 优先夺取同城据点******************************************
                // 优先夺取同城据点(因为会影响大城判断base.status)
                //  如果存在同一城市区域的小城,尽量最高优先
                // 士气等宏观判断在255.cpp进行
                if (pk::get_city_id(dst_base.pos) == src_city_id and dst_base.facility != 设施_城市)
                {
                    weight[dst_id] += 100;
                }
                // ********************************* 地理.路径相关 : 地理.路径类型因子*********************************************
                //  确认地理.路径
                path = pk::get_route(building.get_id(), dst_base.get_id(), building.get_force_id(), true);
                if (path == 路径_无)
                    continue;

#if param_set
                weight[dst_id] += pk::get_attack_param().route_weight[pk::min(2, path)];
#endif
#if not_param_set
                if (path == 路径_一般)
                    weight[dst_id] += int(pk::core["ai.attack.weight.route.land"]); // 50
                else if (path == 路径_海洋)
                    weight[dst_id] += int(pk::core["ai.attack.weight.route.sea"]); // 0
                else
                    weight[dst_id] += int(pk::core["ai.attack.weight.route.other"]); // 0
#endif

                // 舰船数量足够多的时候,海洋也不会限制分数
                舰船数量 = pk::get_weapon_amount(building, 兵器_斗舰) + pk::get_weapon_amount(building, 兵器_楼船);
                if (舰船数量 >= 10 and path == 路径_海洋)
                {
                    weight[dst_id] += pk::min(舰船数量 * 2, 50);
                }


                if (调试模式.v)
                    pk::trace(" 路径类型因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  路径类型:" + path);

                // ********************************* 地理.路径相关 : 实际距离因子******************************************

                int real_distance = unit_distance[src_id][dst_id];

                weight[dst_id] += 50 - pk::max(real_distance, 5) * 10;  //特别近的城市之间没什么区分.

                if (调试模式.v)
                    pk::trace(" 真实距离因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  真实距离:" + real_distance);

                // ********************************* 地理.路径相关 : 据点距离因子******************************************
                // 距离加权
                int distance = pk::get_building_distance(src_id, dst_id, src_force_id);

                // 如果城市之间的间隔为1,但是距点距离为2,在这里还是会减分.
                if (distance > 1)
                    weight[dst_id] += (1 - distance) * 20 + 20;

                // 对于1格城市距离,但是2格据点距离来说,要把分加回来10分(跟第上面的匹配,也就是敌对小据点的分高于大城)
                if (dst_base.facility == 设施_城市)
                {
                    if (pk::get_city_distance(building.get_id(), dst_base.get_id()) == 1 and distance == 2)
                        weight[dst_id] += 10;
                }

                if (dst_base.facility == 设施_城市)
                {
                    if (pk::get_city_distance(building.get_id(), dst_base.get_id()) > 1)
                        weight[dst_id] -= 100;
                }

                if (调试模式.v)
                    pk::trace(" 据点距离因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  距离:" + distance);

                    // ********************************* 地理.路径相关 : 州判定因子******************************************
#if param_set
                bool 同州优先 = pk::get_attack_param().same_province_first;
#endif
#if not_param_set
                bool 同州优先 = bool(pk::core["ai.attack.same_province_first"]);
#endif

                bool 是否同州 = pk::get_province_id(building.pos) == pk::get_province_id(dst_base.pos);
                //if (同州优先 and 是否同州)
                   // weight[dst_id] += 10;

                if (调试模式.v)
                    pk::trace(" 是否同州因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  是否同州:" + 是否同州);

                // ********************************* 地图战略因子****************************************
                int 边缘值 = int(abs(dst_base.pos.x - 100) + abs(dst_base.pos.y - 100));

                if (边缘值 > 75)
                    weight[dst_id] += pk::min((边缘值 - 70), 30);  //有意错开,给边缘城市加底分

                if (调试模式.v)
                    pk::trace(" 地图战略因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "边缘值:" + 边缘值);

                // ********************************* 地优先攻击仅剩一个据点的势力,抢夺人才****************************************
                //仅剩一个据点+100分 1个城市+50分.
                if (ch::get_base_list(pk::get_force(dst_base.get_force_id())).count == 1)
                    weight[dst_id] += 50;


                if (pk::get_city_list(pk::get_force(dst_base.get_force_id())).count <= 1)
                    weight[dst_id] += 50;

                if (调试模式.v)
                    pk::trace(" 势力捡漏因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "边缘值:" + 边缘值);

                // ********************************* 地图战略因子 .州****************************************
                int dst_province_id = pk::get_province_id(dst_base.pos);
                if (dst_province_id == 州_幽州 or dst_province_id == 州_益州 or dst_province_id == 州_荆南 or dst_province_id == 州_凉州)
                    weight[dst_id] += 50;

                if (dst_province_id == 州_扬州 or dst_province_id == 州_南中)
                    weight[dst_id] += 30;

                if (调试模式.v)
                    pk::trace(" 州郡战略因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "目标州:" + dst_province_id);



                // ********************************* 关隘处理因子*****************************************
                int 兵器数量 = pk::get_weapon_amount(dst_base, 兵器_井阑) + pk::get_weapon_amount(dst_base, 兵器_冲车) + pk::get_weapon_amount(dst_base, 兵器_投石) + pk::get_weapon_amount(dst_base, 兵器_木兽);
                if (ch::is_gate(dst_base.get_id()) and dst_id != 铃据点_犍为 and dst_id != 铃据点_郁林)
                {


                    weight[dst_id] += pk::min(0, 兵器数量 * 10 - 200);
                }

                if (调试模式.v)
                    pk::trace(" 关隘处理因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  据点类型:" + dst_base.facility);


                // ********************************* 对于正在进行的目标协同攻击加权*****************************************
                // 对于正在攻击的势力加权,如果正在攻击的势力太多,则大幅降权.
                int total_city_count = pk::get_city_list(src_force).count;

                if (dst_force_id < 势力_末 and dst_force_id > -1)
                {
                    if (attacking_force.contains(dst_force) and attacking_force_troops[dst_force_id] > 20000)
                        weight[dst_id] += 60;
                    if (!attacking_force.contains(dst_force) and (attacking_force.count > (total_city_count / 2 + 1) or attacking_force.count > 3) and attacking_force_troops[dst_force_id] == 0)

                    {
                        if (调试模式.v)
                            pk::trace(" 集中攻击因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  攻击势力过度被中止:" + attacking_force.count);
                        continue;
                    }

                    if (attacking_building_troops[dst_id] > 10000)
                        weight[dst_id] += 60;

                    if (attacking_building.count > (total_city_count) and attacking_building_troops[dst_id] == 0)
                    {
                        if (调试模式.v)
                            pk::trace(" 集中攻击因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  攻击城市过度被中止:" + attacking_building.count);
                        continue;
                    }
                }

                if (调试模式.v)
                    pk::trace(" 集中攻击因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id]);


        // ********************************* 外交相关:友好度因子*****************************************
        //  友好度加权
                int 友好度 = 0;
                if (dst_force_id >= 0 && dst_force_id < 势力_末)
                {
                    友好度 = src_force.relations[dst_force_id];
#if param_set
                    if (src_force.relations[dst_force_id] < uint(pk::get_attack_param().low_relations_target))
                    {
                        weight[dst_id] += pk::get_attack_param().low_relations_weight;
                    }
#endif
#if not_param_set
                    if (src_force.relations[dst_force_id] < uint(pk::core["ai.attack.weight.relations_target"]))
                    {
                        weight[dst_id] += int(pk::core["ai.attack.weight.relations"]);
                    }
#endif
                }

                if (调试模式.v)
                    pk::trace(" 友好度的因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  友好度:" + 友好度);

                // ********************************* 据点相关:人口资源导向因子*****************************************
                // 目标城市的人口越多,权重越高.
                // 100万人口城市+3,20万人口城市-3.

                auto base_t = ch::get_base_p(dst_id);
                int 人口权重 = (int(base_t.population) - 30 * 10000) / 50000;

                weight[dst_id] += pk::max(0, 人口权重);

                if (调试模式.v)
                    pk::trace(" 人口修正因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  人口权重:" + 人口权重);

                // ********************************* 势力相关:势力排名因子*****************************************
                // 尽量避免和大势力对抗

                if ((dst_force_id == -1 or dst_force_id >= 势力_末))
                    dst_rank = force_count;

                else
                {
                    int count_neibor_enemy_force = 0;
                    for (int h = 0; h < 非贼势力_末; h++)
                    {
                        if (ai::force_to_force_enemy_base[src_force_id][h] > 0) count_neibor_enemy_force++;
                    }

                    if (ai::force_to_force_enemy_base[src_force_id][dst_force_id] <= 3 and dst_rank < 2 and force_count > 3 and count_neibor_enemy_force > 2)
                    {
                        if (调试模式.v)
                            pk::trace(" 相邻少大势力:目的地:" + pk::decode(pk::get_name(dst_base)) + "  不招惹相邻不多的大势力:" + ai::force_to_force_enemy_base[src_force_id][dst_force_id]);
                        continue;
                    }


                    if (调试模式.v)
                        pk::trace(" 相邻城市数量:目的地:" + pk::decode(pk::get_name(dst_base)) + "  相邻城市数量:" + ai::force_to_force_enemy_base[src_force_id][dst_force_id] + "  " + src_force_id + " " + dst_force_id);

                    if (ai::force_to_force_enemy_base[src_force_id][dst_force_id] <= 2 and dst_rank < 3 and force_count > 3 and count_neibor_enemy_force > 2)
                        weight[dst_id] += int(dst_rank * 60.0 / force_count);
                        //weight[dst_id] += int(rank_diff * 10.0 / force_list.count);
                }
                // 尽量不去招惹最强的势力,比如说7个势力的时候,不要去打最强的那两个
                if (force_count > 6 and (dst_rank <= force_count / 5 or dst_rank <= 1) and !dst_base.is_player())
                {
                    if (src_rank <= 1) weight[dst_id] -= 150;
                    else weight[dst_id] -= 200;
                }

                if (调试模式.v)
                    pk::trace(" 势力相关因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  目标排名" + dst_rank + "  排名差" + rank_diff + "  势力总数" + force_count);

                //********************************************************************************************************
                // *********************************特别重要!!!!!!:战略选择因子*****************************************
                //********************************************************************************************************

                // 如果一个目标城市和其他城市都不相邻(地图边缘)则加权`
                // 如果一个目标城市的相邻,和出发城市的势力的敌对越多,则降权.
                // 一个目标城市的相邻,和出发城市相邻的己方城市越多,则加权.
                // 举例:南阳有6个相邻,除襄阳之外,的5个城市都是曹操的,刘备在襄阳要打南阳,则会被降权
                // 举例:北平同时可以选择相同条件的南皮和襄平时,如果打下襄平,襄平敌人为0,南皮敌人为4,所以南皮相对襄平减分.
                float neighbor_threat = 0;
                int neighbor_rank = 0;

                dst_near_building_list = ai::base_near_baselist[dst_id];
                for (int j = 0; j < dst_near_building_list.count; j++)
                {
                    int neighbor_base_id = dst_near_building_list[j].get_id();
                    if (neighbor_base_id == -1 or neighbor_base_id >= 据点_末)
                        continue;

                    //此处顺序一定不能写错,指的是,邻居据点是否可以攻击此据点的意思
                    if (ch::get_mid_base_id(neighbor_base_id, dst_id).first == -1 and pk::get_building_distance(neighbor_base_id, dst_id) == 2)
                        continue;

                    if (unit_distance[dst_id][neighbor_base_id] > 8) continue;

                    pk::building @neighbor_base = pk::get_building(neighbor_base_id);
                    bool 大城市 = (neighbor_base.facility == 设施_都市);
                    float 水路影响 = 0;
                    if (pk::get_route(src_id, dst_id, src_force_id, true) == 路径_海洋)
                        水路影响 = 0.5;

                    if (neighbor_base_id == dst_id)
                        continue;

                    if (neighbor_base_id == building.get_id())
                        continue;

                    int neighbor_base_rank = ai::force_list.index_of(pk::get_force(pk::get_building(neighbor_base_id).get_force_id()));

                    // 附近有空城则-1
                    if (pk::get_building(neighbor_base_id).get_force_id() == -1)
                    {
                        neighbor_threat -= 1;
                        continue;
                    }

                    // if (pk::get_city_id(dst_base.pos) == pk::get_city_id(neighbor_base.pos) and dst_base.facility != 设施_都市)
                    //     continue;

                       // 计数目标据点和己方相邻据点,
                       // 和己方据点相邻非常重要,避免战线过长.
                    if (neighbor_base_id > -1 and building.get_force_id() == pk::get_building(neighbor_base_id).get_force_id() and neighbor_base.troops > 20000)
                    {

                        if (unit_distance[dst_id][neighbor_base_id] <= 8)
                            neighbor_threat -= ai::base_atk_power[neighbor_base_id] / 5;

                        else if (unit_distance[dst_id][neighbor_base_id] <= 12)
                            neighbor_threat -= ai::base_atk_power[neighbor_base_id] / 10;
                        continue;
                    }

                    // 计数和自己敌对的相邻据点
                    if (pk::get_building(neighbor_base_id).get_force_id() > -1 and !dst_base.is_player() and pk::is_enemy(building, pk::get_building(neighbor_base_id)))
                    {

                        neighbor_threat += ai::base_atk_power[neighbor_base_id] / 20;

                        if (调试模式.v)
                            pk::trace(" 战略威胁战力计算:目的地:" + pk::decode(pk::get_name(dst_base)) + "  邻居:" + pk::decode(pk::get_name(neighbor_base)) + "  威胁值" + neighbor_threat);

                        // 势力排名越靠前,越威胁大.
                        if (大城市)
                            neighbor_threat += (1 - float(neighbor_base_rank) / float(force_count)) * ((src_rank <= 1) ? 10 : 20);
                        else
                            neighbor_threat += (1 - float(neighbor_base_rank) / float(force_count)) * ((src_rank <= 1) ? 5 : 10);

                        if (调试模式.v)
                            pk::trace(" 战略威胁势力计算:目的地:" + pk::decode(pk::get_name(dst_base)) + "  邻居:" + pk::decode(pk::get_name(neighbor_base)) + "  威胁值" + neighbor_threat);
                    }
                }
                // 地图边缘的城市或者狭隘要地的城市减分
                if (dst_near_building_list.count <= 3)
                {
                    neighbor_threat -= ((3 - dst_near_building_list.count) * 10 + 10);
                }

                weight[dst_id] -= int(pk::min(neighbor_threat, 100.0));

                if (调试模式.v)
                    pk::trace(" 战略要素因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  威胁值" + neighbor_threat);

                // ********************************* 难度修正*****************************************
                // 随着难度提高,增加对玩家的进攻性
                if (dst_base.is_player())
                    weight[dst_id] += (int(pk::get_scenario().difficulty) - 1) * 每级难度影响玩家受攻击权重;


                if (调试模式.v)
                    pk::trace(" 玩家难度因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  难度" + pk::get_scenario().difficulty);

                // ********************************* 难度修正*****************************************
                // 随着性格提高,增加进攻性
                // 胆小的降低出征欲望
                weight[dst_id] += int(kunshu.character * 15) - 10;

                if (调试模式.v)
                    pk::trace(" 性格要素因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  性格" + kunshu.character);

                // ********************************* 随机*****************************************
                // 随机性影响
                int rand_impact = pk::rand(20) - 10;
                weight[dst_id] += rand_impact;

                if (调试模式.v)
                    pk::trace(" 随机要素因子:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id] + "  随机数" + rand_impact);

                // ********************************* 最终修正*****************************************
                // 兵力充足的时候要增加总体出征的分数,避免龟缩的情况.
                weight[dst_id] += pk::get_troops(building) / 1000;
                weight[dst_id] += 己方进攻战斗力 / 5;
                if (force_count <= 5)
                    weight[dst_id] += 己方进攻战斗力 / 2;

                   // 兵力足够多的时候强制进攻
                if (pk::get_troops(building) >= 100000)
                    weight[dst_id] += 300;

                if (调试模式.v)
                    pk::trace(" 最终修正调试模式.v:目的地:" + pk::decode(pk::get_name(dst_base)) + "  分数:" + weight[dst_id]);

                // *********************************如果分数不足,则不进攻*****************************************
                // 势力不够强的时候,不要去打不适合的城市
                // 不能因为仅有一个相邻而破坏自己的战略.除非兵力已满.

                if (weight[dst_id] <= 0)
                    continue;

                if (weight[dst_id] > max_weight)
                {
                    max_weight_building_id = dst_id;
                    max_weight = weight[dst_id];
                }


                if (max_weight_building_id == -1)
                    continue;
            }
            //  building_list.clear();
            if (max_weight_building_id == -1)
                return null;

            if (调试模式.v)
                pk::trace(" 最终返回据点:" + pk::decode(pk::get_name(pk::get_building(max_weight_building_id))));

            @final_base = pk::get_building(max_weight_building_id);
            return pk::get_building(max_weight_building_id);
        }



        int callback(pk::city @city, pk::force @force)
        {
            //pk::trace("func_263");
            if (pk::get_scenario().no == 血色剧本)
                return 0; // 血色进攻倾向应重写--TODO
            int kunshu_id = force.kunshu;
            int city_id = city.get_id();
            int weight = 0;
            if (!pk::is_new_map())
                return 0;
            // 血色无法采用原版的，因为君主id不一样，那就先默认为返回0
            if (!pk::is_new_map())
            {
                switch (kunshu_id)
                {
                    case 武将_袁熙:
                    case 武将_袁尚:
                    case 武将_袁绍:
                    case 武将_袁谭:
                        switch (city_id)
                        {
                            case 城市_襄平:
                            case 城市_蓟:
                            case 城市_晋阳:
                                weight = 1;
                                break;
                            case 城市_北平:
                            case 城市_平原:
                                weight = 2;
                                break;
                            case 城市_南皮:
                            case 城市_邺:
                                weight = 4;
                                break;
                            default:
                                break;
                        }
                    case 武将_曹彰:
                    case 武将_曹植:
                    case 武将_曹操:
                    case 武将_曹丕:
                        switch (city_id)
                        {
                            case 城市_邺:
                            case 城市_濮阳:
                            case 城市_汝南:
                            case 城市_汉中:
                                weight = 1;
                                break;
                            case 城市_陈留:
                            case 城市_许昌:
                            case 城市_洛阳:
                                weight = 4;
                                break;
                            case 城市_宛:
                            case 城市_长安:
                                weight = 2;
                                break;
                            default:
                                break;
                        }
                    case 武将_孙坚:
                    case 武将_孙权:
                    case 武将_孙策:
                        switch (city_id)
                        {
                            case 城市_建业:
                            case 城市_吴:
                                weight = 4;
                                break;
                            case 城市_会稽:
                            case 城市_庐江:
                            case 城市_柴桑:
                                weight = 2;
                                break;
                            case 城市_江夏:
                            case 城市_长沙:
                                weight = 1;
                                break;
                            default:
                                break;
                        }
                    case 武将_刘备:
                        switch (city_id)
                        {
                            case 城市_江夏:
                            case 城市_长沙:
                            case 城市_武陵:
                                weight = 1;
                                break;
                            case 城市_襄阳:
                            case 城市_江陵:
                            case 城市_永安:
                            case 城市_汉中:
                            case 城市_梓潼:
                            case 城市_江州:
                                weight = 2;
                                break;
                            case 城市_成都:
                                weight = 4;
                                break;
                            default:
                                break;
                        }
                }
            }
            return weight;
        }


    }

    Main main;
}